﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YJKFamilyLibDataManager
{
	[DefaultProperty("Family")]
	public class DbFamily
	{
		[Browsable(false)]
		public DbExData ExData { get; set; }

		[Browsable(false)]
		public List<DbParamDefinition> ParamDefinitionList
		{
			get
			{
				return this.paramDefinitionList;
			}
		}

		public List<DbParamDefinition> GetInstanceParamDefinitionListFromDb()
		{
			List<DbParamDefinition> list = new List<DbParamDefinition>();
			List<DbParamDefinition> list2 = new List<DbParamDefinition>();
			list2 = this.Database.FamilyParamTable[this];
			foreach (DbParamDefinition dbParamDefinition in list2)
			{
				if (dbParamDefinition.ParamDefinitionType == ParamDefinitionType.InstanceParam)
				{
					list.Add(dbParamDefinition);
				}
			}
			return list;
		}

		[Browsable(false)]
		public List<string> Symbols
		{
			get
			{
				return this.mDatabase.TypeTable[this];
			}
		}

		[DisplayName("设计版本")]
		[ReadOnly(true)]
		[Category("属性")]
		[Description("设计版本")]
		public int VerNO
		{
			get
			{
				return this.ExData.Eid2;
			}
			set
			{
				this.ExData.Eid2 = value;
			}
		}

		[Description("特征")]
		[DisplayName("特征")]
		[Category("属性")]
		public string Feature
		{
			get
			{
				return this.ExData.Tag1;
			}
			set
			{
				this.ExData.Tag1 = value;
			}
		}

		[Category("属性")]
		[DisplayName("名称")]
		[Description("族名称")]
		[Browsable(false)]
		public string Name
		{
			get
			{
				return this.mName;
			}
			set
			{
				this.mName = value;
			}
		}

		[Category("属性")]
		[Description("族版本")]
		[DisplayName("版本")]
		public string Version
		{
			get
			{
				return this.mVersion;
			}
			set
			{
				this.mVersion = value;
			}
		}

		[DisplayName("日期")]
		[Category("属性")]
		[Description("日期")]
		public DateTime Date
		{
			get
			{
				return this.mDdate;
			}
		}

		public void SetDate(DateTime date)
		{
			this.mDdate = date;
		}

		[DisplayName("描述")]
		[Category("属性")]
		[Description("描述")]
		public string Description
		{
			get
			{
				return this.mDescription;
			}
			set
			{
				this.mDescription = value;
			}
		}

		[Browsable(false)]
		public Guid Guid
		{
			get
			{
				return this.mGuid;
			}
		}

		[Browsable(false)]
		public Guid ParentId
		{
			get
			{
				return this.mParentId;
			}
		}

		[Description("族图片")]
		[DisplayName("图片")]
		[Category("属性")]
		public Image Image
		{
			get
			{
				return this.mImage;
			}
			set
			{
				this.mImage = value;
			}
		}

		[Category("属性")]
		[DisplayName("族大图")]
		[Browsable(false)]
		[Description("族大图")]
		public Image LargeImage
		{
			get
			{
				return this.mLargeImage;
			}
			set
			{
				this.mLargeImage = value;
			}
		}

		[DisplayName("二维图")]
		[Browsable(false)]
		[Category("属性")]
		[Description("二维图")]
		public Image TwoDImage
		{
			get
			{
				return this.mTwoDImage;
			}
			set
			{
				this.mTwoDImage = value;
			}
		}

		[Description("是否能编辑")]
		[Category("属性")]
		[DisplayName("受限")]
		public bool Limit
		{
			get
			{
				return this.mLimit;
			}
			set
			{
				this.mLimit = value;
			}
		}

		[DisplayName("使用次数")]
		[ReadOnly(true)]
		[Category("属性")]
		[Description("使用次数")]
		public int Count
		{
			get
			{
				return this.mCount;
			}
			set
			{
				this.mCount = value;
			}
		}

		[Description("最近使用日期")]
		[Category("属性")]
		[DisplayName("使用日期")]
		public DateTime UseDate
		{
			get
			{
				return this.mUseDate;
			}
		}

		public void SetUseDate(DateTime date)
		{
			this.mUseDate = date;
		}

		[Category("属性")]
		[DisplayName("审核")]
		[Browsable(false)]
		[Description("审核是否通过")]
		public bool Check
		{
			get
			{
				return this.mCheck;
			}
			set
			{
				this.mCheck = value;
			}
		}

		[Browsable(false)]
		public FamilyLibDatabase Database
		{
			get
			{
				return this.mDatabase;
			}
		}

		[Category("属性")]
		[DisplayName("图例名")]
		[Description("图例名")]
		public string KeyName
		{
			get
			{
				return this.mKeyName;
			}
			set
			{
				this.mKeyName = value;
			}
		}

		public void SetDatabase(FamilyLibDatabase db)
		{
			this.mDatabase = db;
		}

		public DbFamily(string name, Image img)
		{
			this.ExData = new DbExData();
			this.mName = name;
			this.mImage = img;
			this.mGuid = Guid.NewGuid();
		}

		public DbFamily(string name, Image img, Guid guid)
		{
			this.mName = name;
			this.mImage = img;
			this.mGuid = guid;
			this.ExData = new DbExData();
		}

		public Family Reload(Autodesk.Revit.DB.Document doc)
		{
			FileInfo familyFile = this.FamilyFile;
			Family family = null;
			Transaction transaction = new Transaction(doc, "LoadFamily");
			try
			{
				string familyName = this.getFamilyName(familyFile.FullName);
				if (family == null)
				{
					Family family2 = null;
					transaction.Start();
					doc.LoadFamily(familyFile.FullName, new DbFamily.MyFamilyLoadOptions(), out family2);
					transaction.Commit();
					if (family2 == null)
					{
						family2 = ElementFiltering.FindFamily(doc, familyName);
					}
					family = family2;
				}
			}
			catch
			{
				if ((int)transaction.GetStatus() == 1)
				{
					transaction.RollBack();
				}
			}
			finally
			{
				familyFile.Delete();
			}
			return family;
		}

		public Family Load(Autodesk.Revit.DB.Document doc)
		{
			FileInfo familyFile = this.FamilyFile;
			Family family = null;
			Transaction transaction = new Transaction(doc, "LoadFamily");
			try
			{
				string familyName = this.getFamilyName(familyFile.FullName);
				family = ElementFiltering.FindFamily(doc, familyName);
				if (family == null)
				{
					Family family2 = null;
					transaction.Start();
					doc.LoadFamily(familyFile.FullName, out family2);
					transaction.Commit();
					family = family2;
				}
			}
			catch
			{
				if ((int)transaction.GetStatus() == 1)
				{
					transaction.RollBack();
				}
			}
			finally
			{
				familyFile.Delete();
			}
			return family;
		}

		public void UseCountAndDatePlus()
		{
			this.Count++;
			this.SetUseDate(DateTime.Now);
			this.mDatabase.FamilyTable.Update(this);
		}

		public Family Load(Autodesk.Revit.DB.Document doc, ref FileInfo file)
		{
			file = this.FamilyFile;
			Family family = null;
			try
			{
				string familyName = this.getFamilyName(file.FullName);
				family = ElementFiltering.FindFamily(doc, familyName);
				if (family == null)
				{
					Family family2 = null;
					Transaction transaction = new Transaction(doc, "LoadFamily");
					try
					{
						transaction.Start();
						doc.LoadFamily(file.FullName, out family2);
						transaction.Commit();
						family = family2;
					}
					catch
					{
						transaction.RollBack();
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
			return family;
		}

		public Family LoadInSubTrans(Autodesk.Revit.DB.Document doc)
		{
			FileInfo familyFile = this.FamilyFile;
			Family family = null;
			try
			{
				string familyName = this.getFamilyName(familyFile.FullName);
				family = ElementFiltering.FindFamily(doc, familyName);
				if (family == null)
				{
					Family family2 = null;
					SubTransaction subTransaction = new SubTransaction(doc);
					subTransaction.Start();
					doc.LoadFamily(familyFile.FullName, out family2);
					subTransaction.Commit();
					family = family2;
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
			finally
			{
				familyFile.Delete();
			}
			return family;
		}

        public void Update(Autodesk.Revit.ApplicationServices.Application app)
		{
			FileInfo familyFile = this.FamilyFile;
			Document document = app.OpenDocumentFile(familyFile.FullName);
			string text = Path.GetTempPath() + Guid.NewGuid().ToString() + ".rfa";
			RevitVersionFuncs.SaveAs(document, text);
			document.Close(true);
			FileInfo fileInfo = new FileInfo(text);
			try
			{
				this.mDatabase.FamilyFileTable.Replace(this, fileInfo);
			}
			catch
			{
			}
			finally
			{
				fileInfo.Delete();
				familyFile.Delete();
			}
		}

		public DbFamily GetKeyFamily()
		{
			DbCategory dbCategory = this.Database.CategoryTable[this.ParentId];
			DbFamily result = null;
			if (this.mDatabase is SqliteDatabase)
			{
				result = FamilyLibDatabase.GetSqliteDB(SubjectType.System, this.Version).FamilyTable[this.KeyName];
			}
			else if (this.mDatabase is SqlServerDatabase)
			{
				result = FamilyLibDatabase.GetSqlServerDB(SubjectType.System, this.Version, ((SqlServerDatabase)this.mDatabase).ConnectData).FamilyTable[this.KeyName];
			}
			return result;
		}

		private string getFamilyName(string fullName)
		{
			int num = fullName.LastIndexOf("\\");
			int num2 = fullName.LastIndexOf(".");
			return fullName.Substring(num + 1, num2 - num - 1);
		}

		private FileInfo FamilyFile
		{
			get
			{
				return this.mDatabase.FamilyFileTable[this];
			}
		}

		public void SetParentId(Guid id)
		{
			this.mParentId = id;
		}

		public bool Remove(bool force)
		{
			if (force)
			{
				return this.Database.FamilyTable.Remove(this);
			}
			if (this.Limit)
			{
				throw new Exception("无法删除系统族");
			}
			return this.Database.FamilyTable.Remove(this);
		}

		public bool Rename(string newName)
		{
			if (this.Limit)
			{
				throw new Exception("系统族无法改名");
			}
			this.mName = newName;
			return this.mDatabase.FamilyTable.Update(this);
		}

		public bool ChangeParent(Parent newParent)
		{
			if (this.Limit)
			{
				throw new Exception("系统族无法移动");
			}
			this.SetParentId(newParent.Guid);
			return this.Database.FamilyTable.Update(this);
		}

		public bool AddType(DataTable typeTable)
		{
			DbTransaction tr = this.mDatabase.StartTransaction();
			bool result;
			try
			{
				result = this.mDatabase.TypeTable.Add(typeTable, this, tr);
			}
			catch
			{
				result = false;
			}
			finally
			{
				this.mDatabase.CommitTransaction(tr);
			}
			return result;
		}

		public bool UpdateTypeTableColumn(List<DbParamDefinition> pdList)
		{
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			bool result;
			using (DbTransaction dbTransaction = this.mDatabase.StartTransaction())
			{
				try
				{
					this.Database.FamilyParamTable.Remove(this, dbTransaction);
					this.Database.FamilyParamTable.Add(this, pdList, dbTransaction);
					this.Database.TypeTable.AddColumns(this, pdList, dbTransaction);
					this.mDatabase.CommitTransaction(dbTransaction);
					result = true;
				}
				catch (Exception ex)
				{
					this.mDatabase.RollbackTransaction(dbTransaction);
					throw ex;
				}
				finally
				{
					if (this.mDatabase.Connection.State == ConnectionState.Open)
					{
						this.mDatabase.Connection.Close();
					}
				}
			}
			return result;
		}

		public void RecordTypes(Autodesk.Revit.DB.Document doc, FamilyLibDatabase db, string fileName)
		{
			Family family = FamilyUtil.LoadFamily(doc, fileName);
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			DataTable dataTable = db.TypeTable.DataTable(this);
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
			foreach (FamilySymbol familySymbol in family.GetSymbols())
			{
				DataRow dataRow = dataTable.NewRow();
				dataRow["规格名"] = familySymbol.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString();
				foreach (object obj in dataTable.Columns)
				{
					DataColumn dataColumn = (DataColumn)obj;
					Parameter parameter = familySymbol.GetParameter(dataColumn.ColumnName);
					if (parameter != null && !parameter.IsReadOnly)
					{
						dataRow[dataColumn] = this.getParamValue(doc, parameter);
					}
				}
				dataTable.Rows.Add(dataRow);
			}
			this.AddType(dataTable);
		}

		private string getParamValue(Autodesk.Revit.DB.Document doc, Parameter param)
		{
			string result = "";
            switch ((int)param.StorageType)
			{
			case 1:
				result = 0.ToString();
				try
				{
					result = param.AsInteger().ToString();
                    if ((int)param.DisplayUnitType != -2)
					{
						result = ((double)param.AsInteger() * Convert.ToDouble(UnitConvertC.ImperialDutRatio(param.DisplayUnitType))).ToString();
					}
					return result;
				}
				catch
				{
					return result;
				}
				goto Block_5;
			case 2:
				result = 0.0.ToString();
				try
				{
                    if ((int)param.DisplayUnitType != -2)
					{
						result = Math.Round(param.AsDouble() * Convert.ToDouble(UnitConvertC.ImperialDutRatio(param.DisplayUnitType)), 1).ToString();
					}
					else
					{
						result = Math.Round(param.AsDouble(), 1).ToString();
					}
					return result;
				}
				catch
				{
					return result;
				}
				break;
			case 3:
				goto IL_F6;
			case 4:
				break;
			default:
				return result;
			}
			ElementId id = param.AsElementId();
			Element element = RevitVersionFuncs.GetElement(doc, id);
			if (element != null)
			{
				return element.Name;
			}
			return result;

			Block_5:
            IL_F6:
			try
			{
				result = param.AsString();
			}
			catch
			{
			}
			return result;
		}

		public void GetTypeParams(Autodesk.Revit.DB.Document doc, Family family, DbCategory category)
		{
			List<DbParamDefinition> list = category.GetParamDefinitionList();
			using (Document document = doc.EditFamily(family))
			{
				try
				{
					if (document.IsFamilyDocument)
					{
						FamilyManager familyManager = document.FamilyManager;
						FamilyParameterSet parameters = familyManager.Parameters;
						int num = 0;
						foreach (object obj in parameters)
						{
							FamilyParameter familyParameter = (FamilyParameter)obj;
							if (familyParameter.Formula == null && !familyParameter.IsInstance)
							{
								string name = familyParameter.Definition.Name;
								DbParamDefinition dbParamDefinition = new DbParamDefinition(name, familyParameter.Definition.ParameterType, ParamDefinitionType.TypeParam, familyParameter.Definition.ParameterGroup);
								foreach (DbParamDefinition dbParamDefinition2 in list)
								{
									if (dbParamDefinition2.Name == name)
									{
										dbParamDefinition.mLimit = true;
										break;
									}
								}
                                DisplayUnitType displayUnitType = (DisplayUnitType)(-2);
								try
								{
									displayUnitType = familyParameter.DisplayUnitType;
								}
								catch
								{
								}
								dbParamDefinition.DisplayUnitType = displayUnitType;
								dbParamDefinition.CustomName = familyParameter.Definition.Name;
								dbParamDefinition.SetOrder(num);
								dbParamDefinition.StorageType = familyParameter.StorageType;
								num++;
								this.paramDefinitionList.Add(dbParamDefinition);
							}
						}
					}
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message);
				}
				finally
				{
					document.Close(false);
				}
			}
		}

		public SubjectType GetSubjectType()
		{
			if (this.Database != null)
			{
				return this.Database.SubjectTable.SubjectType;
			}
			throw new Exception("未加入数据库。");
		}

		public override string ToString()
		{
			return this.Name;
		}

		public override bool Equals(object obj)
		{
			DbFamily dbFamily = obj as DbFamily;
			return dbFamily != null && (this.mGuid.Equals(dbFamily.mGuid) && this.Date.Equals(dbFamily.Date));
		}

		public override int GetHashCode()
		{
			return this.mName.GetHashCode();
		}

		private List<DbParamDefinition> paramDefinitionList = new List<DbParamDefinition>();

		private string mName;

		private string mVersion;

		private DateTime mDdate;

		private string mDescription = "";

		private Guid mGuid;

		private Guid mParentId;

		private Image mImage;

		private Image mLargeImage;

		private Image mTwoDImage;

		private bool mLimit;

		private int mCount;

		private DateTime mUseDate;

		private bool mCheck;

		protected FamilyLibDatabase mDatabase;

		private string mKeyName;

		private class MyFamilyLoadOptions : IFamilyLoadOptions
		{
			public bool OnFamilyFound(bool familyInUse, out bool overwriteParameterValues)
			{
				overwriteParameterValues = true;
				return true;
			}

			public bool OnSharedFamilyFound(Family sharedFamily, bool familyInUse, out FamilySource source, out bool overwriteParameterValues)
			{
				source = 0;
				overwriteParameterValues = true;
				return true;
			}
		}
	}
}
